package com.example.lib_base.base;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.Bundle;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.fragment.app.Fragment;

/*
一个fragment/activity对应一个viewModel

其他viewModel可作为共享数据源

* */


public abstract class DataBindingFragment extends Fragment {

    private static  final String TAG = "DataBindingFragment";

    protected AppCompatActivity mActivity;
    private ViewDataBinding mBinding;
    private TextView mTvStrictModeTip;

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        mActivity = (AppCompatActivity) context;
    }
    //配置DataBinding
    protected abstract DataBindingConfig getDataBindingConfig();


    protected abstract void initViewModel();

    protected abstract void initViewOrObserve();

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        initViewModel();
    }


    /**
     * TODO tip: 警惕使用。非必要情况下，尽可能不在子类中拿到 binding 实例乃至获取 view 实例。使用即埋下隐患。
     * 目前的方案是在 debug 模式下，对获取实例的情况给予提示。
     *
     *不拿实例就要一些@BindingAdapter 来对View来设置操作，麻烦，简单的状态设值通过viewModel还好，
     * 但有些变得复杂了些，把部分代码抽离了。。//21/10/20 long
     * 而且在基类中可先增加binding判空 至于拿到的view实例空不空只能由开发者决定
     * <p>
     * @return binding
     */
    protected ViewDataBinding getBinding() {
//        if (isDebug() && mBinding != null) {
//            if (mTvStrictModeTip == null) {
//                mTvStrictModeTip = new TextView(getContext());
//                mTvStrictModeTip.setAlpha(0.5f);
//                mTvStrictModeTip.setPadding(
//                        mTvStrictModeTip.getPaddingLeft() + 24,
//                        mTvStrictModeTip.getPaddingTop() + 64,
//                        mTvStrictModeTip.getPaddingRight() + 24,
//                        mTvStrictModeTip.getPaddingBottom() + 24);
//                mTvStrictModeTip.setGravity(Gravity.CENTER_HORIZONTAL);
//                mTvStrictModeTip.setTextSize(10);
//                mTvStrictModeTip.setBackgroundColor(Color.WHITE);
//                @SuppressLint({"StringFormatInvalid", "LocalSuppress"})
//                String tip = getString(R.string.debug_databinding_warning, getClass().getSimpleName());
//                mTvStrictModeTip.setText(tip);
//                ((ViewGroup) mBinding.getRoot()).addView(mTvStrictModeTip);
//            }
//        }
        return mBinding;
    }

    @Nullable
    @Override
    public View onCreateView(
            @NonNull LayoutInflater inflater,
            @Nullable ViewGroup container,
            @Nullable Bundle savedInstanceState
    ) {

        DataBindingConfig dataBindingConfig = getDataBindingConfig();
        //TODO tip: DataBinding 严格模式：
        // 将 DataBinding 实例限制于 base 页面中，默认不向子类暴露，
        // 通过这样的方式，来彻底解决 视图调用的一致性问题，
        // 如此，视图调用的安全性将和基于函数式编程思想的 Jetpack Compose 持平。
        ViewDataBinding binding = DataBindingUtil.inflate(inflater, dataBindingConfig.getLayout(), container, false);
        binding.setLifecycleOwner(getViewLifecycleOwner());
        if (dataBindingConfig.getStateViewModel() != null)
        binding.setVariable(dataBindingConfig.getVmVariableId(), dataBindingConfig.getStateViewModel());
        SparseArray<Object> bindingParams = dataBindingConfig.getBindingParams();
        for (int i = 0, length = bindingParams.size(); i < length; i++) {
            binding.setVariable(bindingParams.keyAt(i), bindingParams.valueAt(i));
        }
        mBinding = binding;
        return binding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        if (mBinding != null)
            initViewOrObserve();
    }

    public boolean isDebug() {
        return mActivity.getApplicationContext().getApplicationInfo() != null &&
                (mActivity.getApplicationContext().getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mBinding.unbind();
        mBinding = null;
    }
}
